package classify;

import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;

public class DecisionTree {
    public static int attribute,length;
    public static int gain_rate(Instances instances){
        int choice=0;
        double info_decision=0,max_ratio=0;
        double []Info=new double[attribute-1];
        double []Gain=new double[attribute-1];
        double []Gain_ratio=new double[attribute-1];
        for(int i=0;i<instances.attributeStats(attribute-1).distinctCount;i++){
            double count=instances.attributeStats(attribute-1).nominalWeights[i];
            info_decision+=(-count/length*Math.log(count/length));
        }
        for(int i=0;i<attribute-1;i++){
            int distinctCount=instances.attributeStats(i).distinctCount;
            int []count=search(instances,i,distinctCount);
            for(int j=0;j<distinctCount;j++){
                double statistic=instances.attributeStats(i).nominalWeights[j];
                Gain_ratio[i]-=Math.round(statistic/length*Math.log(statistic/length)*10000000)*1.0/10000000;
                Info[i]+= Math.round((((count[j] - statistic) * Math.log((statistic-count[j]) / statistic) - count[j] * Math.log(count[j] / statistic)) / length) * 10000000)*1.0/10000000;
            }
            Gain[i]=info_decision-Info[i];
            Gain_ratio[i]=Gain[i]/Gain_ratio[i];
        }
        for(int i=0;i<attribute-1;i++){
            if(Gain_ratio[i]>max_ratio){
                max_ratio=Gain_ratio[i];
                choice=i;
            }
        }
        return choice;
    }

    public static int[] search(Instances instances,int i,int distinctCount){
        int []count=new int[distinctCount];
        for(int j=0;j<length;j++){
            if(instances.instance(j).value(attribute-1)==0) {
                for(int k=0;k<distinctCount;k++){
                    if(k==instances.instance(j).value(i)){
                        count[k]+=1;
                        break;
                    }
                }
            }
        }
        return count;
    }

    public static void creat_tree(Instances instances,int choice,int []yes_count,Node<String> root,Tree<String> strTree){
        int distinctCount=instances.attributeStats(choice).distinctCount;
        for(int i=0;i<distinctCount;i++){
            int count=instances.attributeStats(choice).nominalCounts[i];
            Node<String> newNode=new Node<String>(instances.attribute(choice).value(i),yes_count[i],count);
            strTree.addNewNode(root,newNode);
        }
    }

    public static void creat_Node(Tree<String> strTree,Node<String> root,Instances instances,int choice){
        for(Node<String> tempNode:root.getNodeList()){
            if((tempNode.get_yes_Count()!=tempNode.getCount())&&(tempNode.get_yes_Count()!=0)){
                Instances newInstances=new Instances(instances);
                newInstances.clear();
                for(int i=0;i<length;i++){
                    if(instances.instance(i).toString(choice).compareTo(tempNode.getCont())==0){
                        newInstances.add(instances.instance(i));
                    }
                }
                newInstances.deleteAttributeAt(choice);
                length=newInstances.size();
                attribute=newInstances.numAttributes();
                int new_choice=gain_rate(newInstances);
                int []count=search(newInstances,new_choice,newInstances.attributeStats(new_choice).distinctCount);
                creat_tree(newInstances,new_choice,count,tempNode,strTree);
                tempNode.category=newInstances.attribute(new_choice).name();
                creat_Node(strTree,tempNode,newInstances,new_choice);
                length=instances.size();
                attribute=instances.numAttributes();
            }else if(tempNode.get_yes_Count()==0){
                String strings=Integer.toString(tempNode.getCount());
                tempNode.category="no("+strings+","+"0)";
            }else{
                String strings=Integer.toString(tempNode.getCount());
                tempNode.category="yes("+strings+","+"0)";
            }
        }
    }

    public static void main(String[] args) throws Exception {
        int choice,yes_count;
        DataSource source = new DataSource("/home/tang/weather.nominal.arff");
        Instances instances = source.getDataSet();
        attribute=instances.numAttributes();
        length=instances.size();
        choice=gain_rate(instances);
        yes_count=instances.attributeStats(attribute-1).nominalCounts[0];
        Tree<String> strTree=new Tree<String>(new Node<String>(instances.attribute(choice).name(),yes_count,length));
        Node<String> root=strTree.getRoot();
        int []count=search(instances,choice,instances.attributeStats(choice).distinctCount);
        creat_tree(instances,choice,count,root,strTree);
        creat_Node(strTree,strTree.getRoot(),instances,choice);
        strTree.traversal(strTree.getRoot());
    }
}
